package com.qf.fcy.youshare.utils;

/**
 * Created with IntelliJ IDEA.
 * User: Alex[FR]
 * Date: 2015/2/6
 * Email: alex_fcy@163.com
 */

import android.graphics.Bitmap;
import android.os.Build;
import android.support.v4.util.LruCache;

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.LinkedHashMap;

/**
 * 提供两个对外的接口方法
 * Bitmap getImage(String url) 通过网址获取在缓存中实际的Bitmap,
 * 如果没有Bitmap,如果没有Bitmap 返回null
 * putImage(String url,Bitmap bitmap)存储Bitmap到缓存中
 * <p/>
 * 图片缓存工具，只进行内存图片的管理，如果需要进行文件缓存管理，请调用 FileCache 进行操作
 */
public class ImageCache {
    private static ImageCache ourInstance;

    public static ImageCache getInstance() {
        // lazy
        if (ourInstance == null) {
            ourInstance = new ImageCache();
        }
        return ourInstance;
    }

    // 1.声明一级缓存，缓存在内容中有固定的大小，如果缓存超过这个大小限制，那么
    // 删除最旧的缓存条目，再添加新的内容
    /**
     * 一级缓存采用固定内存尺寸的方式存储部分内容，
     * 当空间不足的时候，采用LRU算法将很少使用、很长时间没有使用的替换掉
     * LruCache需要在每次添加对象的时候，进行占用内存空间大小的监测，
     * 当总体的内存超过限制，那么删掉最近最少使用的对象，因此每次添加必须计算内存占用。
     */
    private LruCache<String, Bitmap> firstCache;

    // 2.声明第二级缓存，缓存就是直接采用HashMap进行存储，存储的对象就是SoftReference
    // 来引用的对象，HashMap的操作，可以一直添加
    // 当内存不足的时候，会直接回收，因此可以充分利用内存，尽可能多的在内存中保存Bitmap的实例
    // 因为内存访问非常快
    private HashMap<String, SoftReference<Bitmap>> secondCache;

    private ImageCache() {
        // LruCache 构造方法的参数代表:当前的缓存在内存中最大占用多少字节
        // 官方建议LruCache 最大内存字节数为当前手机系统可用内存的1/8
        long freeMemory = Runtime.getRuntime().freeMemory();

        if (freeMemory > 0) {
            freeMemory = freeMemory / 8;
        } else {
            freeMemory = 5 * 1024 * 1024;
        }
        firstCache = new LruCache<String, Bitmap>((int) freeMemory) {
            // 重写

            @Override
            protected int sizeOf(String key, Bitmap value) {
                int size = 0;
                // Android 判断SDK版本号
                if (Build.VERSION.SDK_INT >= 19) {
                    // API 19才能用
                    size = value.getAllocationByteCount();
                } else {
                    int rowBytes = value.getRowBytes(); // 一行的字节数
                    int height = value.getHeight();
                    size = rowBytes * height;
                }

                return super.sizeOf(key, value);
            }
        };

        secondCache = new LinkedHashMap<String, SoftReference<Bitmap>>();
    }

    /**
     * 获取内存缓存中指定url地址的图片
     *
     * @param url String 图片地址
     * @return Bitmap 对象
     */
    public Bitmap getImage(String url) {
        Bitmap ret = null;
        if (url != null) {
            // 先从第一级缓存查找，找到，直接返回，未找到从二级查找
            ret = firstCache.get(url);
            if (ret == null) { // 第一级没有，查找第二级
                if (secondCache.containsKey(url)) {
                    // 如果第二级有url的引用，那么查找内部的数据
                    // 第二级内部数据由于SoftReference, 很可能获取出来的结果就是null
                    SoftReference<Bitmap> softReference = secondCache.get(url);
                    if (softReference != null) {
                        ret = softReference.get(); // 获取引用的实际对象
                    }

                }
            }
        }

        return ret;
    }

    public void putImage(String url, Bitmap bitmap) {
        if (url != null && bitmap != null) {
            // 更新第二级缓存
            secondCache.put(url, new SoftReference<Bitmap>(bitmap));

            // 更新一级缓存
            firstCache.put(url, bitmap);
        }
    }
}
